import { reactive, ref } from 'vue'
import axios from 'axios'

/**
 * UnwrapRef: vue3的类型工具，可以将Ref对象还原为原始的值类型
 * | :TS的联合类型  只能赋值指定的类型，如果赋值其它类型就会报错
 * T,E 定义查询结果的类型
 * U定义参数的类型
 */
// export interface RequestState<T, E, U> {
//     loading: boolean;
//     result: UnwrapRef<T | E>;
//     oldParams?: UnwrapRef<U>;
// }

/**
 * auto:是否自动请求
 * headers:类型声明的意思是
 * HTTP 请求头可以是一个普通的键值对对象，也可以是由多个键值对对象组成的数组，以满足不同请求的需求
 * params：请求的参数
 * onOk: 请求响应成功回调函数，对返回数据处理，生成新的数据
 * onError: 请求失败的回调函数
 *
 * <T, E, P> T:
 */
// export interface OtherParams<T, E, P> {
//     auto?: boolean;
//     headers?:
//     | {
//         [key: string]: string;
//     }
//     | {
//         [key: string]: string;
//     }[];
//     params?: P;
//     onOk?: (result: E) => T;
//     onError?: (error: AxiosError) => void;
// }

/**
 * 其他参数
 * auto:是否自动发送
 * headers:请求头信息
 * onOk:请求成功回调
 * onError:请求失败回调
 * params: post请求的 params参数
 */
export const defOtherParams = {
  auto: false
}

/**
 * @description GET请求Hook
 * @param url 请求url
 * @param params 请求参数
 * @param resp 默认响应数据
 * @param other 自定义参数信息
 * @returns
 */
// @ts-expect-error
export const useGet = (url, params, resp, other = defOtherParams) => {
  // 解构出自定义参数信息
  // @ts-expect-error
  const { auto, headers, onOk, onError } = { ...defOtherParams, ...other }
  // 定义state数据
  const state = reactive({
    loading: false,
    result: resp,
    oldParams: params
  })

  // @ts-expect-error
  const send = (params?, newUrl?) => {
    state.loading = true
    axios
      .get(newUrl || url, {
        params,
        headers
      })
      .then((res) => {
        // setTimeout(() => {
        // }, 3000);
        // console.log('res', res);
        const { data } = res
        // 给state赋值
        state.loading = false
        state.result = ref(data).value
        state.oldParams = ref(params).value
        if (onOk) {
          onOk(data)
        }
      })
      .catch((err) => {
        if (onError) {
          onError(err)
        }
        // 给state赋值
        state.loading = false
        state.result = ref(resp).value
        state.oldParams = ref(params).value
      })
  }

  if (auto) {
    send()
  }

  return [state, send]
}

// const useGet = <U, T, E, P>(
//     url: string,
//     params: U,
//     resp: T | E,
//     other: OtherParams<T, E, P> = defOtherParams
// ):
//     [RequestState<T, E, U>, (params?: U, newUrl?: string) => void] => {
//     const state = reactive({
//         loading: false,
//         result: null,
//     })
//     const { auto, headers, onError, onOk } = { ...defOtherParams, ...other };

//     const send = (params?: U, newUrl?: string) => {
//         state.loading = true;
//         axios.get<T | E>

//     }
//     return [state, send];
// }

/**
 * @description POST请求Hook
 * @param url 请求url
 * @param body 请求参数
 * @param resp 默认响应数据
 * @param other 自定义参数信息
 * @returns
 */
// @ts-expect-error
export const usePost = (url, body, resp, other = defOtherParams) => {
  // 解构出自定义参数信息
  // @ts-expect-error
  const { auto, headers, params, onOk, onError } = { ...defOtherParams, ...other }
  // 定义state数据
  const state = reactive({
    loading: false,
    result: resp
  })

  // @ts-expect-error
  const send = (body?, params?, newUrl?) => {
    state.loading = true
    axios
      .post(newUrl || url, body, {
        params,
        headers
      })
      .then((res) => {
        // setTimeout(() => {

        // }, 3000);
        // console.log('res', res);
        const { data } = res
        // 给state赋值
        state.loading = false
        state.result = ref(data).value
        if (onOk) {
          onOk(data)
        }
      })
      .catch((err) => {
        if (onError) {
          onError(err)
        }
        // 给state赋值
        state.loading = false
        state.result = ref(resp).value
      })
  }

  if (auto) {
    send(body, params)
  }

  return [state, send]
}
